// components/qs-calendar/index.js

const dayNum = {
  week: 7,
  month: 7 * 5,
};

Component({
  options: {
    multipleSlots: true, // 在组件定义时的选项中启用多slot支持
    pureDataPattern: /^_/ // 指定所有 _ 开头的数据字段为纯数据字段
  },
  /**
   * 组件的属性列表
   */
  properties: {
    /**
     * type 日历显示模式 （未实现：day天/week周）
     * month月/day天/week周
     */
    type: {
      type: String,
      value: 'month',
    },
    // 尺寸，mini|auto｜normal，默认auto
    size: {
      type: String,
      value: 'auto',
    },
    // 选中的日期，range、multiple模式为数组
    value: null,
    // 补充数据，被传递到每日组件里
    addedData: null,
    // 扩展数据，自动添加到每日项里，格式：{"2021-06-01":anyData}，那么“2021-06-01”的item.extendData里可以获取到anyData
    extendData: null,
    // 多选日期，仅在month显示模式下，多选比区域优先级高
    multiple: Boolean,
    // 范围选日期，仅在month显示模式下
    range: Boolean,
    // fixed 固定头 (未实现)
    fixedHead: Boolean,
    // 过期日期禁用
    overDisable: Boolean,
    // overDay 过期效果
    overDay: Boolean,
    // showBackToday 显示返回今天
    showBackToday: {
      type: Boolean,
      value: true
    },
    // scroll 滚动显示日期（未实现）
    scroll: Boolean,
    // 周末显示名字默认格式
    weekLang: {
      type: Object,
      value: {
        1: '日',
        2: '一',
        3: '二',
        4: '三',
        5: '四',
        6: '五',
        7: '六',
      },
    },
  },

  /**
   * 外部样式类
   */
  externalClasses: ['active-class'],

  /**
   * 组件的初始数据
   */
  data: {
    // newDate: null, // 当前日期
    themeSize: 'auto', // 主题尺寸
    todayInWeek: false, // 今天是否本周
    // setYear: '', // 设置年
    // setMonth: '',  // 设置月
    // setDay: '', // 设置日
    // setDate: '',  // 设置日期
    // setFirstDate: '', // 设置第一天日期
    // setWeekDate: 0, // 设置星期模式的日期
    // setWeekMonth: '', // 设置星期模式的月份
    // setWeekYear: '', // 设置星期模式的年份
    // showDayNum: 7 * 5, // 显示天的格数
    changeDate: '', // 变化日期
    selectedDate: [], // 选中的日期
    calendarData: [], // 日历数据
    calendarTitle: '', // 日历标题
    // headHeight: '', // 头高度
    // calendarDayStyle: {}, // 日历天样式
    _obs_value_oldVal: []
  },
  /**
   * 监听变化
   */
  observers: {
    value(newVal) {
      let _newVal = newVal
      let _oldVal = this.data._obs_value_oldVal
      if (newVal instanceof Array && _oldVal instanceof Array) {
        _newVal = [...newVal].sort().toString()
        _oldVal = _oldVal.sort().toString()
        this.data._obs_value_oldVal = [...newVal]
      } else {
        this.data._obs_value_oldVal = newVal
      }
      if (_newVal === _oldVal) {
        return
      }
      this.initData()
    },
    extendData() {
      this.initData()
    },
    multiple() {
      this.initData()
    },
    range() {
      this.initData()
    },
    // addedData(val) {
    //   console.log(val)
    // },
    size(val) {
      this.setData({
        themeSize: val || 'auto'
      })
    }
  },
  /**
   * 创建周期不能使用setData
   */
  created() {
    this._timeoutId = null
    const newDate = new Date()
    this.newDate = newDate
  },
  /**
   * 进入页面节点树时
   */
  attached() {
    this.showDayNum = dayNum[this.data.type] || 35
    this.initData()
  },
  /**
   * 组件渲染完成
   */
  ready() {

  },
  /**
   * 组件的方法列表
   */
  methods: {
    getSizeRect() {
      if (this.data.size !== 'auto') {
        return
      }
      const _setSize = (val) => {
        if (this.data.themeSize === val) {
          return
        }
        this.setData({
          themeSize: 'mini'
        })
      }
      this.createSelectorQuery().select('.qs-calendar').boundingClientRect((rect) => {
        if (rect.width < 230) {
          _setSize('mini')
        } else {
          _setSize('auto')
        }
      }).exec()
    },
    initData() {
      if (this._timeoutId) {
        clearTimeout(this._timeoutId)
      }
      // 使用setTimeout防止重复执行
      this._timeoutId = setTimeout(() => {
        this.getSizeRect()
        let arrayValue = this.data.value
        let date = this.data.value
        if (arrayValue instanceof Array) {
          arrayValue = arrayValue.filter(v => v && new Date(v).toString() !== 'Invalid Date').sort()
          if (arrayValue.length > 0) {
            date = arrayValue[0]
            this.lastEndDate = arrayValue[-1] || ''
          } else {
            date = ''
            this.data.value = ''
          }
        }

        if (typeof date === 'string') {
          date = new Date(date.replace(/-/g, '/'))
        }

        if (date.toString() === 'Invalid Date') {
          date = ''
          this.data.value = ''
        }

        date = date || this.newDate

        this._qsc_value = date
        this._qsc_valueDate = this.getDateStr(date, '-')
        this.setYear = date.getFullYear();
        this.setMonth = date.getMonth() + 1;
        this.setDay = date.getDay();
        this.setDate = date.getDate();

        // 设置选中
        if ((this.data.multiple || this.data.range) && arrayValue instanceof Array) {
          if (this.data.range) {
            this.data.selectedDate = arrayValue.slice(0, 2)
          } else {
            this.data.selectedDate = arrayValue
          }
        } else {
          if (this.data.value) {
            this.data.selectedDate = [this._qsc_valueDate]
          } else {
            this.data.selectedDate = []
          }
        }

        this.lastClickDate = ''
        this.showCalendarData(this._qsc_value);
      }, 0)
    },
    handleClick(e) {
      const val = e.currentTarget.dataset.item
      if (this.data.overDisable && val.isOver) {
        return
      }
      this.changeDate = val.date;
      if (this.data.multiple) {
        const _idx = this.data.selectedDate.indexOf(val.date)
        if (_idx > -1) {
          this.data.selectedDate.splice(_idx, 1)
        } else {
          this.data.selectedDate.push(val.date)
        }
      } else if (this.data.range) {
        let [startDate = val.date, endDate = val.date] = this.data.selectedDate
        const isDoubleClick = this.lastClickDate === val.date
        if (isDoubleClick) {
          startDate = val.date
          endDate = val.date
          this.isAgainStart = true
          this.isAgainEnd = false
        } else if (startDate >= val.date || (startDate < val.date && endDate > val.date)) { // 小于开始或者大于开始且小于结束，那就放开始
          this.isAgainStart = val.date == startDate
          if (startDate < val.date && this.isAgainEnd && !this.isAgainStart) {
            this.isAgainStart = false
            this.isAgainEnd = true
            endDate = val.date
          } else {
            this.isAgainEnd = false
            startDate = val.date
          }
        } else if (endDate <= val.date) {
          this.isAgainStart = false
          this.isAgainEnd = true
          endDate = val.date
        }
        this.lastClickDate = val.date
        this.data.selectedDate = [startDate, endDate]
      } else {
        if (this.data.selectedDate.length > 0 && this.data.selectedDate[0] === val.date) {
          this.data.selectedDate = []
        } else {
          this.data.selectedDate = [val.date]
        }
      }
      // 返回一个元组,[选中日对象,选中多选或区域]
      this.triggerEvent('change', [val, this.data.selectedDate]);
      const setDate = new Date(val.year, val.month - 1, val.day);  // 传入时间
      this.showCalendarData(setDate);
    },
    showNewData() {
      this.showCalendarData(this.newDate);
    },
    // 年翻页
    toNextYear() {
      this.setYear += 1;
      const setDate = new Date(this.setYear, this.setMonth - 1, 1);  // 当前月第一天
      this.showCalendarData(setDate);
    },
    toPrevYear() {
      this.setYear -= 1;
      const setDate = new Date(this.setYear, this.setMonth - 1, 1);  // 当前月第一天
      this.showCalendarData(setDate);
    },
    // 月翻页
    toNextMonth() {
      this.setMonth += 1;
      if (this.setMonth >= 13) {
        this.setMonth = 1;
        this.setYear += 1;
      }
      const setDate = new Date(this.setYear, this.setMonth - 1, 1);  // 当前月第一天
      this.showCalendarData(setDate);
    },
    toPrevMonth() {
      this.setMonth -= 1;
      if (this.setMonth <= 1) {
        this.setMonth = 12;
        this.setYear -= 1;
      }
      const setDate = new Date(this.setYear, this.setMonth - 1, 1);  // 当前月第一天
      this.showCalendarData(setDate);
    },
    // 星期翻页
    toNextWeek() {
      this.setWeekDate += 7;
      const setDate = new Date(this.setWeekYear, this.setWeekMonth - 1, this.setWeekDate);
      this.showCalendarData(setDate);
    },
    toPrevWeek() {
      this.setWeekDate -= 7;
      const setDate = new Date(this.setWeekYear, this.setWeekMonth - 1, this.setWeekDate);
      this.showCalendarData(setDate);
    },
    getDayCountOfMonth(year, month) {
      if (month === 3 || month === 5 || month === 8 || month === 10) {
        return 30;
      }
      if (month === 1) {
        if ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0) {
          return 29;
        }
        return 28;
      }
      return 31;
    },
    /**
       * 日期转化为字符串， 4位年+2位月+2位日
       */
    getDateStr(date, min) {
      const year = date.getFullYear();
      let month = date.getMonth() + 1; // 月从0开始计数
      let d = date.getDate();
      const divide = min || '';

      month = (month > 9) ? (`${month}`) : (`0${month}`);
      d = (d > 9) ? (`${d}`) : (`0${d}`);
      return year + divide + month + divide + d;
    },
    /**
     * 表格中显示数据，并设置类名
     */
    showCalendarData(setDate) {
      const calendarDataList = [];
      const extendData = this.data.extendData && { ...this.data.extendData }
      this.calendarData = [];
      let weekIsDou = false;
      const year = setDate.getFullYear();
      const month = setDate.getMonth() + 1;
      const dateStr = this.getDateStr(setDate);
      let isOverWeek = false;
      this.todayInWeek = false;
      // 设置表格中的日期数据
      const firstDay = new Date(year, month - 1, 1);  // 当前月第一天
      // 偏移原理就是 当前天减去本周第几天
      const offsetDay = this.type === 'week' ? setDate.getDate() - setDate.getDay() : 1 - firstDay.getDay();

      let showDayNum = this.showDayNum
      if (this.data.type === 'month' && showDayNum <= 35) {
        const stLastDay = new Date(year, month - 1, showDayNum - 1 + offsetDay)
        const reLastDay = new Date(year, month, 1).getTime() - 1000 * 60 * 60 * 24
        // 获取本月最后一天，天设置0。此方法不知兼容性如何
        // const reLastDay = new Date(year, month, 0) 
        showDayNum += stLastDay < reLastDay ? 7 : 0
      }

      for (let i = 0; i < showDayNum; i += 1) {
        const thisDay = new Date(year, month - 1, i + offsetDay);
        const thisDayStr = this.getDateStr(thisDay);
        const dateObj = {
          day: '', // 日
          month: '', // 月
          year: '', // 年
          date: '', // 日期
          week: '', // 星期
          isToday: false, // 是否今天
          isMonth: false, // 是否本月
          isOver: false, // 是否过期
          isSelected: false, // 是否选中
          isLastClick: false, // 是否最近激活
          inRange: false, // 是否在区域内
          isRangeFirst: false, // 是否区域第一个
          isRangeLast: false, // 是否区域最后一个
          extendData: null // 扩展数据, 根据extendData的key映射
        };
        if (i === 0) {
          this.setWeekDate = thisDay.getDate();
          this.setWeekMonth = thisDay.getMonth() + 1;
          this.setWeekYear = thisDay.getFullYear();
        }
        dateObj.day = thisDay.getDate();
        dateObj.week = thisDay.getDay();
        dateObj.month = thisDayStr.substr(4, 2);
        dateObj.year = thisDayStr.substr(0, 4);
        dateObj.date = this.getDateStr(thisDay, '-');
        if (extendData && extendData[dateObj.date]) {
          dateObj.extendData = extendData[dateObj.date]
        }
        if (thisDayStr === this.getDateStr(new Date())) {
          // 当前天
          dateObj.isToday = true;
          // this.changeDate = dateObj.date;
          this.todayInWeek = true;
        } else if (Date.parse(thisDay) < Date.parse(new Date())) {
          dateObj.isOver = true;
          isOverWeek = true;
        }
        if (thisDayStr.substr(0, 6) === this.getDateStr(firstDay).substr(0, 6)) {
          // 当前月
          dateObj.isMonth = true;
        } else if (this.type === 'week') {
          weekIsDou = true;
        }
        // 是否选中
        dateObj.isSelected = this.data.selectedDate.includes(dateObj.date)

        // 区域
        if (!this.data.multiple && this.data.range) {
          dateObj.inRange = this.data.range && (this.data.selectedDate[0] <= dateObj.date && this.data.selectedDate[1] >= dateObj.date)
          dateObj.isRangeFirst = this.data.selectedDate[0] === dateObj.date
          dateObj.isRangeLast = this.data.selectedDate[1] === dateObj.date
        }

        // 是否最近点击
        dateObj.isLastClick = this.lastClickDate === dateObj.date
        calendarDataList.push(dateObj);
      }

      this.calendarData = calendarDataList;

      if (weekIsDou) {
        this.calendarTitle = `${this.calendarData[0].year}年${this.calendarData[0].month}月
           / ${this.calendarData[6].year}年${this.calendarData[6].month}月`;
        this.setMonth = parseInt(this.calendarData[6].month, 0);
        this.setYear = parseInt(this.calendarData[6].year, 0);
      } else {
        // 设置顶部标题栏中的 年、月信息
        this.calendarTitle = `${dateStr.substr(0, 4)}年${dateStr.substr(4, 2)}月`;
        this.setMonth = month;
        this.setYear = year;
      }

      // setData
      this.setData({
        calendarTitle: this.calendarTitle,
        calendarData: this.calendarData,
        todayInWeek: this.todayInWeek,
        changeDate: this.changeDate || '',
      })

      const calendarData = {};
      calendarData.isOverWeek = isOverWeek;
      calendarData.isToWeek = this.todayInWeek;
      calendarData.list = calendarDataList;
      this.triggerEvent('changDate', calendarData);
    },
  }
})
